/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package wave;
import ast.*;
import base.*;
import base.TrackNode.Echo;
import base.WaveEnvironment.Mode;
import communicator.message.MsgWave;
import java.util.ArrayList;
import java.util.Vector;
import trackmsg.ActivateMsg;
import trackmsg.EchoMsg;
import trackmsg.ExpandhMsg;
import trackmsg.TrackCtrlMsg;
import trackmsg.ExpandRemoteTrack;

/**
 *
 * @author Vu Duc Tiep
 */
public class ASTHopAheadExecution extends WaveExecution {
    public ASTHopAheadExecution(WaveHeadParser parser, WaveEnvironment waveEnv){
        super(parser, waveEnv);
    }

    public void execute(ASTHopAhead hop, String tail) {
        Utilities.WPPrint("Execute HOP Ahead: " + hop.getString());
        //Bien kiem tra xem co trong che do CREATE hay ko
        boolean isCreate = waveEnv.getWaveMode() == Mode.CREATE;
        boolean isExpand = false;
        String currentNodeName = waveEnv.getCONTENT();
        SimpleNode left = (SimpleNode)hop.jjtGetChild(0);
        SimpleNode right = (SimpleNode)hop.jjtGetChild(1);
        
        if(left instanceof ASTAnyLink){ //ANY##ALL
            ArrayList<KNLink> allLinks = kn.getKNNode(currentNodeName).getAllLinks();
            if(right instanceof ASTAllNodes){
                for(KNLink link : allLinks){
                    if(!link.getDesNodeName().equals(waveEnv.getPREDECESSOR())){
                        if(link.isLinkedWithOtherComputer())
                            isExpand = sendWaveOut(currentNodeName, link.getDesNodeName(), link.getName(), tail, waveEnv, link.getDesHostAddr());
                        else
                            isExpand = sendWave(currentNodeName, link.getDesNodeName(), link.getName(), tail, waveEnv);
                    }
                } 
            }  
        } else { //link##ALL
            Vector vLeft = getASTNodeValue((SimpleNode)left.jjtGetChild(0));
            ArrayList<KNLink> allLinks = kn.getKNNode(currentNodeName).getAllLinks();
            Utilities.WPPrint("OK@#@#@#@####################################################{" + vLeft);
            for(KNLink link : allLinks){
                if(vLeft.contains(link.getNameWithSign()) && !link.getDesNodeName().equals(waveEnv.getPREDECESSOR())){
                    if(link.isLinkedWithOtherComputer())
                        isExpand = sendWaveOut(currentNodeName, link.getDesNodeName(), link.getName(), tail, waveEnv, link.getDesHostAddr());
                    else
                        isExpand = sendWave(currentNodeName, link.getDesNodeName(), link.getName(), tail, waveEnv);
                }
            }
        }
        if(waveEnv.getTrackAddress() != null){//Kiem tra trong che do track
            TrackNode currentTrack = wi.getTrackForest().
                    getTrackNode(waveEnv.getTrackAddress());
            TrackCtrlMsg msg = new ActivateMsg(currentTrack);
            if(!isExpand) msg = new EchoMsg(currentTrack, Echo.FALSE);
            wi.getTrackQueue().incoming(msg);
        }
    }      
    private boolean sendWave(String srcNode, String desNode, String link,
            String tail, WaveEnvironment waveEnv){
        WaveEnvironment newEnv = new WaveEnvironment(waveEnv);
        Utilities.WPPrint("Move from " + srcNode + " by " + link + " to " + desNode);
        newEnv.setCONTENT(desNode);
        newEnv.setPREDECESSOR(srcNode);
        newEnv.setLINK(link);
        if(waveEnv.getTrackAddress() != null){
            TrackNode currentTrack = wi.getTrackForest().
                    getTrackNode(waveEnv.getTrackAddress());
            TrackCtrlMsg msg;
            msg = new ExpandhMsg(currentTrack, tail, newEnv);
            wi.getTrackQueue().incoming(msg);
            return true;
        } else {
            Wave newWave = new Wave(tail, newEnv);
            this.waveQueue.incomingFront(newWave);
            Utilities.WPPrint(newEnv.toString());
            return false;
        }
    }
    private boolean sendWaveOut(String srcNode, String desNode, String link, String tail, WaveEnvironment waveEnv, String desComputer){
        WaveEnvironment newEnv = new WaveEnvironment(waveEnv);
        Utilities.WPPrint("Move from " + srcNode + " by " + link + " to " + desNode);
        newEnv.setCONTENT(desNode);
        newEnv.setPREDECESSOR(srcNode);
        newEnv.setLINK(link);
        if(waveEnv.getTrackAddress() != null){
            TrackNode currentTrack = wi.getTrackForest().
                    getTrackNode(waveEnv.getTrackAddress());
            TrackCtrlMsg msg;
            msg = new ExpandRemoteTrack(currentTrack, tail, newEnv, desComputer);
            wi.getTrackQueue().incoming(msg);
            return true;
        } else {
            Wave newWave = new Wave(tail, newEnv);
            MsgWave msg = new MsgWave(newWave);
            msg.setDestinationComputer(desComputer);
            wi.getPropagationQueue().incoming(msg);
            return false;
        }
    }
}
